const express = require('express')
const multer = require('multer')
const moment = require('moment')
const path = require('path')
const fs = require('fs')
const resolver = require('./service/resolver.js')
const request = require('./service/request.js')
const { createSocketServer } = require('./service/socket.js')
const app = express()
const config = global.config

// 支持跨域
app.all('*', function (req, res, next) {
  let lpath = req.path.toLowerCase()
  let method = req.method.toLowerCase()

  // 允许的请求头
  res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,HEAD,OPTIONS')
  let headers = config.headers || {}
  for (let key in headers) {
    res.setHeader(key, headers[key])
  }

  // 允许跨域访问
  if (config.isCrossOrigin) {
    res.setHeader('Access-Control-Allow-Origin', '*')
    res.setHeader("Access-Control-Allow-Credentials", "true")
  }

  // 动态origin
  if (String(config.isDynamicOrigin) === '1' || String(config.isDynamicOrigin) === 'true') {
    res.setHeader("Access-Control-Allow-Origin", req.headers.origin || '*')
  }

  if (/options|head/i.test(method)) {
    res.status(204).send('OK')
    res.end()
  }
  // 通用请求或已经请求
  else {
    next()
  }
})
// app.use(cors()) // 允许跨域

// 设置中间件和路由
app.use(express.json()) // 解析JSON数据
app.use(express.urlencoded({ extended: true })) // 解析URL编码数据

// 配置存储选项
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    // 如果没有 uploads 文件夹，则创建文件夹
    const uploadDir = config.uploadPath
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true })
    }
    cb(null, uploadDir)
  }
})

// 使用multer中间件处理文件上传
const upload = multer({ dest: 'temp/', storage: storage })

// 上传
app.post('/upload', upload.single('file'), (req, res) => {
  // 获取上传的文件
  const file = req.file
  // 获取文件的扩展名
  const ext = file.originalname.split('.').pop()
  // 生成新的文件名，格式为年月日_时分秒.txt  
  const newName = moment().format('YYYYMMDD_HHmmss') + '.' + ext
  // 将文件从临时目录移动到当前目录，并重命名文件
  fs.rename(file.path, config.uploadPath + '/' + newName, (err) => {
    if (err) {
      console.error(err)
      const data = {status: 500, success: 0, message: '上传失败', data: null}
      return res.status(500).send(JSON.stringify(data))
    }
    console.log(`File ${file.originalname} has been uploaded and saved as ${newName}`)
    const data = {status: 200, success: 1, message: '上传成功', data: { name: newName }}
    res.send(JSON.stringify(data))
  })
})

// 文件断点续传
app.post('/upload-chunk', upload.single('file'), (req, res) => {
  const { fileName, chunkNumber, chunkTotal } = req.body;
  if (!fileName || chunkNumber === undefined || chunkTotal === undefined) {
    return res.status(400).send('Filename, chunkNumber or chunkTotal is missing')
  }
  // 缓存分片文件
  const tempFilePath = path.join(config.tempPath, `${fileName}.part${chunkNumber}`)
  // 在将磁盘中上传的 原生 chunk 名称更改为 fileName.part0
  // xxxx 变更为 xxx.part0
  fs.renameSync(req.file.path, tempFilePath);

  // 合并文件逻辑
  if (Number(chunkNumber) + 1 === Number(chunkTotal)) {
    const finalFilePath = path.join(config.uploadPath, fileName)
    const writeStream = fs.createWriteStream(finalFilePath)
    for (let i = 0; i < chunkTotal; i++) {
      const chunkPath = path.join(config.tempPath, `${fileName}.part${i}`)
      const data = fs.readFileSync(chunkPath) // 读取 chunk 文件
      writeStream.write(data)
      fs.unlinkSync(chunkPath) // 逐一删除 chunk 文件
    }
    writeStream.end()
  }

  // 响应
  const data = {
    status: 200,
    success: 1,
    message: '上传成功',
    data: {
      name: fileName,
      chunkNumber, chunkTotal,
      progress: (((chunkNumber + 1) / chunkTotal) * 100).toFixed(2)
    }
  }
  res.send(JSON.stringify(data))
})

// 下载
app.post('/download', (req, res) => {
  resolver.solveRequest(req).then(data => {
    let params = data.params
    request.downloadByPath({
      path: config.uploadPath + '/' + params.name,
      dir: config.downloadPath,
      callback: () => {
        const data = {status: 200, success: 1, message: '下载成功', data: null}
        res.status(200).send(JSON.stringify(data))
      }
    })
  }).catch(() => {
    const data = {status: 500, success: 0, message: '下载失败', data: null}
    res.status(500).send(JSON.stringify(data))
  })
})

// 静态目录
app.use('/', express.static(config.accessRootDir))

// 启动服务器并监听端口
app.listen(config.PORT, () => {
  console.log('Web服务端->http://127.0.0.1:' + config.PORT)
})

createSocketServer({ app })